
using System;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using Godot;
using Godot.Collections;

//世界事件
public class WorldEvent
{
    private BlockData top, bottom, left, right;
    public Vector3I Position;
    public Vector2 chunkLocation;
    public BlockWorld world;
    public BlockData block;
    public WorldEvent()
    {

    }
    public WorldEvent(BlockWorld world, Vector3I Position)
    {
        this.world = world;
        this.Position = Position;
    }
    public BlockData GetBlockData()
    {
        return this.world.GetBlock(Position);
    }
    public BlockMaterial GetBlockMaterial(string name)
    {
        return Materials.GetBlockMaterial(name);
    }
    private bool eqblock(BlockData block, string name, String group, int type)
    {
        if (block is null) return false;
        if (block.Name == name)
        {
            if (group != null)
            {
                if (group == block.GetMaterial().Group)
                {
                    if (type != -1)
                    {
                        if (type == top.GetMaterial().type)
                        {
                            return true;
                        }
                        else
                        {
                            return false;
                        }
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return true;
            }
        }
        return false;
    }

    public bool eqTop(string name, String group = null, int type = -1)
    {
        return eqblock(TopBlock(), name, group, type);
    }
    public bool eqBottom(string name, String group = null, int type = -1)
    {
        return eqblock(BottomBlock(), name, group, type);
    }
    public bool eqLeft(string name, String group = null, int type = -1)
    {
        return eqblock(LeftBlock(), name, group, type);
    }
    public bool eqRight(string name, String group = null, int type = -1)
    {
        return eqblock(RightBlock(), name, group, type);
    }

    public BlockData TopBlock()
    {
        return top ?? world.GetBlock(Position + new Vector3I(0, 1));
    }
    public BlockData BottomBlock()
    {
        return bottom ?? world.GetBlock(Position + new Vector3I(0, -1));
    }
    public BlockData LeftBlock()
    {
        return left ?? world.GetBlock(Position + new Vector3I(-1, 0));
    }
    public BlockData RightBlock()
    {
        return right ?? world.GetBlock(Position + new Vector3I(1, 0));
    }
    public BlockData GetFontBlock()
    {
        if (block.Rotate == 0) return world.GetBlock(block.position.X, block.position.Y + 1, block.position.Z);
        else if (block.Rotate == 1) return world.GetBlock(block.position.X + 1, block.position.Y, block.position.Z);
        else if (block.Rotate == 2) return world.GetBlock(block.position.X, block.position.Y - 1, block.position.Z);
        else if (block.Rotate == 3) return world.GetBlock(block.position.X - 1, block.position.Y, block.position.Z);
        return null;
    }
    public BlockData GetBackBlock()
    {
        if (block.Rotate == 0) return world.GetBlock(block.position.X, block.position.Y - 1, block.position.Z);
        else if (block.Rotate == 1) return world.GetBlock(block.position.X - 1, block.position.Y, block.position.Z);
        else if (block.Rotate == 2) return world.GetBlock(block.position.X, block.position.Y + 1, block.position.Z);
        else if (block.Rotate == 3) return world.GetBlock(block.position.X + 1, block.position.Y, block.position.Z);
        return null;
    }
}
//方块更新事件
public class UpdataTickEvent : WorldEvent
{
    //根据周围方块计算图块值
    public int GetAngle<T>(bool redstone = false)
    {
        bool equals(BlockData bd) { return bd != null && ((bd.blockEntity != null && bd.blockEntity is T) || bd.Name == block.Name || (redstone && bd.GetMaterial().redstone)); };
        int angle = 0;
        BlockData up = TopBlock();
        BlockData down = BottomBlock();
        BlockData left = LeftBlock();
        BlockData right = RightBlock();
        if (equals(left) && !equals(down) && !equals(up) && !equals(right)) angle = 1;
        else if (equals(up) && !equals(down) && !equals(right) && !equals(left)) angle = 2;
        else if (equals(right) && !equals(left) && !equals(down) && !equals(up)) angle = 3;
        else if (equals(down) && !equals(left) && !equals(up) && !equals(right)) angle = 4;

        else if (equals(left) && equals(up) && !equals(down) && !equals(right)) angle = 5;
        else if (equals(up) && equals(right) && !equals(left) && !equals(down)) angle = 6;
        else if (equals(right) && equals(down) && !equals(up) && !equals(left)) angle = 7;
        else if (equals(down) && equals(left) && !equals(up) && !equals(right)) angle = 8;

        else if (equals(down) && equals(left) && equals(up) && !equals(right)) angle = 9;
        else if (equals(left) && equals(up) && equals(right) && !equals(down)) angle = 10;
        else if (equals(up) && equals(right) && equals(down) && !equals(left)) angle = 11;
        else if (equals(right) && equals(down) && equals(left) && !equals(up)) angle = 12;

        else if (equals(right) && equals(left) && !equals(up) && !equals(down)) angle = 13;
        else if (equals(up) && equals(down) && !equals(left) && !equals(right)) angle = 14;

        else if (!equals(down) && !equals(left) && !equals(up) && !equals(right)) angle = 0;
        else if (equals(down) && equals(left) && equals(up) && equals(right)) angle = 15;

        return angle;
    }
    public UpdataTickEvent(BlockWorld world, Vector3I location) : base(world, location)
    {
    }
}
//玩家事件
public class PlayerEvent : WorldEvent
{
    public Player player;
    public PlayerEvent(Player player, BlockWorld world, Vector3I location) : base(world, location)
    {
        this.player = player;
    }
}
public class PlayerRotateBlockEvent : PlayerEvent
{
    public PlayerRotateBlockEvent(Player player, BlockWorld world, Vector3I location) : base(player, world, location)
    {
        this.player = player;
    }
}
//玩家放置方块事件
public class PlayerPlaceBlockEvent : PlayerEvent
{
    public PlayerPlaceBlockEvent(Player player, BlockWorld world, Vector3I location) : base(player, world, location)
    {
        this.player = player;
    }
}
public class PlayerUseItemEvent : PlayerEvent
{
    public int z;
    public enum PlayerUseItemSlotType { Curosr, Hand }
    public ItemStack item;
    public PlayerUseItemSlotType slotType;
    public PlayerUseItemEvent(Player player, ItemStack item, BlockWorld world, Vector3I location) : base(player, world, location)
    {
        this.item = item;
    }
}
//玩家使用/右键方块事件
public class PlayerUseBlockEvent : PlayerEvent
{
    public PlayerUseBlockEvent(Player player, BlockWorld world, Vector3I location) : base(player, world, location) { }
}

//玩家破坏方块事件
public class PlayerBreakBlockEvent : PlayerEvent
{
    public Dictionary<string, int> dorps = new Dictionary<string, int>();
    public bool SelfDrop = true;
    public PlayerBreakBlockEvent(Player player, BlockWorld world, Vector3I location) : base(player, world, location)
    {
    }
}